/**
 *
 * populates the nodeDomain
 * NodeReader - reads the node data and creates the corresponding data structures to represent these nodes
 * NodeList - contains the list of nodes and their attributes
 * NodeGraph - node dependencies - nodes and their relationships with each other
 * NodeTimeline - the temporal representation of the nodes
 *
 */
class NodeDomainReader
{
    static Logger logger = new Logger()

    /*
     * reads the node 
     * read the row that represents the node and fill its attributes
     */
    static def readNodeList(RowDataReader rowDataReader)
    {
        def nodeList = new NodeObjList()

        // read the node list
        logger.info("Reading Node List")
        logger.info("Columns:"+rowDataReader.getFieldNames())

        rowDataReader.iterate({ row -> 
            //println row.lastLineNumber() + ". " + row.getValueByLabel("Node") + " of type:" + row.getValueByLabel("Type") + "->"+row.getValueByLabel("Attr1") + "," + row.getValueByLabel("Attr2")

            NodeObj node = new NodeObj(row.getValueByLabel("Node"), row.getValueByLabel("Type"))
            def fieldNames = row.getLabels()
            fieldNames.each {
                if(!it.equalsIgnoreCase("Node") && !it.equalsIgnoreCase("Type"))
                {
                    node.attrs.put(it, row.getValueByLabel(it))
                }
            }

            nodeList.nodes.put(node.name, node)
            logger.info("\t|--" + row.lastLineNumber() + ". added Node:"+node)
        })

        return nodeList
    }


    /**
     * read the node graph
     */
    static def readNodeGraph(NodeObjList nodeList, RowDataReader rowDataReader)
    {
        def nodeGraph = new NodeGraph()
        
        // now read the node graph        
        logger.info("Reading node dependencies:")
        logger.info("FieldNames:"+rowDataReader.getFieldNames())

        rowDataReader.iterate({ row -> 
            //println row.lastLineNumber() + ". " + row.getValueByLabel("Edge Caption")+":"+row.getValueByLabel("Start Node")+"->"+row.getValueByLabel("End Node")
                NodeEdge nodeEdge = new NodeEdge()

                nodeEdge.caption =  row.getValueByLabel("Edge Caption")
                nodeEdge.nodeStartName =  row.getValueByLabel("Start Node")
                nodeEdge.nodeEndName =  row.getValueByLabel("End Node")

                // first check if the nodes exist in the master list
                if(nodeList.nodes[nodeEdge.nodeStartName]==null)
                    logger.info("\t|--"+row.lastLineNumber() + ". ERROR: in reading graph - " + nodeEdge.nodeStartName + " was not found.")
                else if(nodeList.nodes[nodeEdge.nodeEndName]==null)
                    logger.info("\t|--"+row.lastLineNumber() + ". ERROR: in reading timeline - " + nodeEdge.nodeEndName + " was not found.")                
                else
                    nodeGraph.nodeEdges.add(nodeEdge)

                logger.info("\t|--"+ row.lastLineNumber() + ". added NodeEdge:"+nodeEdge)
        })

        return nodeGraph
    }


    /**
     * reads the node timeline
     */
    static def readNodeTimeline(String domainName, NodeObjList nodeList, RowDataReader rowDataReader)
    {
        def nodeTimeline = new NodeTimeline()
        
        // now read the node graph        
        logger.info("Reading node timeline:")
        logger.info("Field names:"+rowDataReader.getFieldNames())

        rowDataReader.iterate({ row -> 
                //println row.lastLineNumber() + ". " + row.getValueByLabel("Node")+":"+row.getValueByLabel("Start Date")+":"+row.getValueByLabel("End Date")

                String nodeName = row.getValueByLabel("Node")
                EventPt eventPt = EventPtsUtil.getEventPtFromStrings(domainName,
                                                                        nodeName,
                                                                        row.getValueByLabel("Start Date"), 
                                                                        row.getValueByLabel("Start Time"), 
                                                                        row.getValueByLabel("End Date"), 
                                                                        row.getValueByLabel("End Time"), 
                                                                        row.getValueByLabel("Is Duration"), 
                                                                        row.getValueByLabel("Is Exact"))

                // first check if the nodes exist in the master list
                if(nodeList.nodes[nodeName] != null)
                {
                    nodeList.nodes[nodeName].eventPt = eventPt
                    logger.info("\t|--"+row.lastLineNumber() + ". " + nodeName + ": added Timeline:" + eventPt)
                }
                else
                {
                    logger.info("\t|--"+row.lastLineNumber() + ". " + nodeName + ": ERROR: in reading timeline - " + nodeName + " was not found.")
                }
        })

        return nodeTimeline
    }


    /**
     * This initializes the domain from the domain folder which could be local or remote
     * - it reads the files from the domain folder which could be local or on http
     * - the CSV files are named by convention rather than configuration
     */
    static NodeDomain initFromDomainFolder(String domainName, String sourceDocsLocation)
    {
        NodeDomain nodeDomain = new NodeDomain(domainName, sourceDocsLocation)
        
        RowDataSource dataSource = new RowDataSource(sourceDocsLocation+"/"+nodeDomain.name+"_list.csv", "CSV")
        RowDataReader rowDataReader = new CSVDataReader(dataSource)
        nodeDomain.nodeList = NodeDomainReader.readNodeList(rowDataReader)

        dataSource = new RowDataSource(sourceDocsLocation+"/"+nodeDomain.name+"_graph.csv", "CSV")
        rowDataReader = new CSVDataReader(dataSource)
        nodeDomain.nodeGraph = NodeDomainReader.readNodeGraph(nodeDomain.nodeList, rowDataReader)

        dataSource = new RowDataSource(sourceDocsLocation+"/"+nodeDomain.name+"_timeline.csv", "CSV")
        rowDataReader = new CSVDataReader(dataSource)
        nodeDomain.nodeTimeline = NodeDomainReader.readNodeTimeline(nodeDomain.name, nodeDomain.nodeList, rowDataReader)

        return nodeDomain
    }


    /**
     * reads the generic example files and creates the node graph for the domain
     */
    static NodeDomain initFromGenericExample()
    {
        String domainName = "MyDomain"

        String docsLocation_local = "./MyDomain.backup"
        String docsLocation_remote = "http://localhost:8080/MyDomain"
        String docsLocation = docsLocation_local

        NodeDomain nodeDomain = NodeDomain.initFromDomainFolder(domainName, docsLocation)

        return nodeDomain
    }


    /**
     *
     */
    static void main(args)
    {
        // GENERIC BUILT-IN EXAMPLE
        //NodeDomain nodeDomain = NodeDomainReader.initFromGenericExample()
        
        // REMOTE EXAMPLE
        //NodeDomain nodeDomain = NodeDomainReader.initFromDomainFolder("MyDomain", "http://localhost:8080/")
        
        // LOCAL EXAMPLE
        NodeDomain nodeDomain = NodeDomainReader.initFromDomainFolder("MyDomain.backup", "./MyDomain.backup")
    }
}
